#!/usr/bin/env python
# encoding: utf-8
"""
game.py

Created by Morgan Quirk on 2007-07-04.
"""

import pygame
import piece
import board
import sys
import random

rndpiece=   {
    0:piece.Piece_Line,
    1:piece.Piece_T,
    2:piece.Piece_L,
    3:piece.Piece_J,
    4:piece.Piece_S,
    5:piece.Piece_Z,
    6:piece.Piece_Square,
            }

class Game:
    def __init__(self, level=0):
        self.screen=pygame.display.set_mode((360,760))
        self.board=board.Board((20,100),(10,20))
        self.level=level
        self.currentpiece=None
        self.nextpiece=None
        self.gridsize=32
        self.clock=pygame.time.Clock()
        
        self.right_timer=None
        self.left_timer=None
        self.last_pieces=[]
        self.points=0
        
        self.lines=(2+level)**1.5
        
        self.effect_clear=[]
        
        pygame.font.init()
        
        self.points_font=pygame.font.Font("SF Square Head.ttf",17)
        self.level_font=pygame.font.Font("SF Square Head.ttf",26)        
        
        self.lvlsurf=self.level_font.render("lvl:"+str(self.level),1, (0,0,0),(255,255,255))
        self.ptsurf=self.points_font.render(str(self.points),1, (0,0,0),(255,255,255))
        
    def run(self):
        while 1:
            self.clock.tick(40)
            #print self.clock.get_fps()
            for event in pygame.event.get():
                if event.type==pygame.QUIT:
                    sys.exit()
                    
                if event.type==pygame.KEYDOWN:
                    if event.key in [pygame.K_RIGHT,pygame.K_KP6]:
                        if self.currentpiece is not None and self.currentpiece.falling:
                            self.currentpiece.shift(+1,self.board)
                        self.right_timer=7
                            
                    if event.key in [pygame.K_LEFT, pygame.K_KP4]:
                        if self.currentpiece is not None and self.currentpiece.falling:                  
                            self.currentpiece.shift(-1, self.board)
                        self.left_timer=7
                            
                    if event.key in [pygame.K_SPACE, pygame.K_KP3]:
                        if self.currentpiece is not None and self.currentpiece.falling:
                            if not self.currentpiece.test_collision( [(x+self.currentpiece.x,y+self.currentpiece.y+1) for (x,y) in self.currentpiece.rotations[self.currentpiece.rotation]], self.board):
                                self.currentpiece.fallnow=99
                            else:
                                self.currentpiece.locktimer=1
                            
                    if event.key in [pygame.K_DOWN, pygame.K_KP2]:
                        if self.currentpiece is not None and self.currentpiece.falling:
                            self.currentpiece.fallnow=1
                            
                    if event.key in [pygame.K_COMMA, pygame.K_UP, pygame.K_KP1]:    #Rotate Counter-Clockwise
                        if self.currentpiece is not None:
                            self.currentpiece.rotate(1, self.board)
                    if event.key in [pygame.K_PERIOD, pygame.K_KP7]:    #Rotate Clockwise
                        if self.currentpiece is not None:
                            self.currentpiece.rotate(-1, self.board)
                                
                if event.type==pygame.KEYUP:
                    key=pygame.key.name(event.key)
                    
                    if event.key in [pygame.K_RIGHT,pygame.K_KP6]:
                        self.right_timer=None
                        
                    if event.key in [pygame.K_LEFT, pygame.K_KP4]:
                        self.left_timer=None
                        
                                
            self.screen.fill((255,255,255))
            self.screen.blit(self.ptsurf,(20,4))
            self.screen.blit(self.lvlsurf,(272,58))                        
            
            if self.left_timer is not None:
                self.left_timer-=1
                
            if self.right_timer is not None:
                self.right_timer-=1
                
            if self.left_timer<=0 and self.left_timer is not None:
                for i in range(max(self.level-20,1)):                
                    self.currentpiece.shift(-1, self.board)
                
            if self.right_timer<=0 and self.right_timer is not None:
                for i in range(max(self.level-20,1)):                
                    self.currentpiece.shift(1, self.board)                
            
            for x,y in self.board.get_filled():
                c1=self.board.colors[x][y]
                pygame.draw.rect(self.screen, c1, (x*self.gridsize+self.board.x, y*self.gridsize+self.board.y,self.gridsize, self.gridsize), 0)
            
            if self.currentpiece is None:
                self.currentpiece=self.nextpiece

                self.nextpiece=None
                
            if self.nextpiece is None:
                rndval=random.randint(0,6)
                i=0
                while rndval in self.last_pieces and i<4:
                    i+=1
                    rndval=random.randint(0,6)
                self.last_pieces.append(rndval)
                if len(self.last_pieces)>4:
                    self.last_pieces.pop(0)
                fr=max((20-self.level)*2,2)
                fb=min(max(int((self.level-20)/2),1),20)
                self.nextpiece=rndpiece[rndval](lockdelay=15, fallrate=fr, fallblocks=fb)       #Make the piece
            
            if self.currentpiece is not None:
                if self.currentpiece.tick(self.board):
                    loss=self.board.add_piece(self.currentpiece)
                    if loss==1:
                        return
                    self.currentpiece=self.nextpiece
                    self.nextpiece=None
                
                if self.currentpiece.locktimer is not None:
                    c1=[max(0,v-(100-(self.currentpiece.locktimer*1.0/self.currentpiece.lockdelay)*100)) for v in self.currentpiece.color]
                else:
                    c1=self.currentpiece.color
                c3=[max(0,v-100) for v in self.currentpiece.color]  #Outline Color
                
                for x,y in self.currentpiece.rotations[self.currentpiece.rotation]:
                    if y+self.currentpiece.y>-1:
                        x1=(x+self.currentpiece.x)*self.gridsize+self.board.x
                        y1=(y+self.currentpiece.y)*self.gridsize+self.board.y       
                    
                    
                        pygame.draw.rect(self.screen, c1, (x1+1,y1+1,self.gridsize-2,self.gridsize-2),0)  #Base, filled
                        pygame.draw.rect(self.screen, c3, (x1,y1,self.gridsize,self.gridsize),1)          #Outline, pixel       
            lines=0
            for y in range(self.board.h):
                xt=0
                for x in range(self.board.w):
                    if self.board.grid[x][y]==1:
                        xt+=1
                if xt>=self.board.w:
                    self.board.drop(y)
                    self.effect_clear.append((0,y))
                    lines+=1
            self.lines+=lines
                    
            pts=self.points
            if lines==1:
                self.points+=40*(self.level+1)
            elif lines==2:
                self.points+=100*(self.level+1)
            elif lines==3:
                self.points+=300*(self.level+1)
            elif lines==4:
                self.points+=1200*(self.level+1)       
            if pts<self.points:
                self.ptsurf=self.points_font.render(str(self.points),1, (0,0,0),(255,255,255))
            
            i=0
            for x,y in self.effect_clear:
                if x>(self.board.w*self.gridsize/2):
                    self.effect_clear.pop(i)
                else:
                    pygame.draw.line(self.screen, (0,255,255), (self.board.x+x, self.board.y+y*self.gridsize), (self.board.x-x+self.board.w*self.gridsize, self.board.y+y*self.gridsize),3)
                    pygame.draw.line(self.screen, (255,255,255), (self.board.x+x, self.board.y+y*self.gridsize), (self.board.x-x+self.board.w*self.gridsize, self.board.y+y*self.gridsize),1)                    
                    self.effect_clear[i]=(x+self.gridsize,y)
                    i+=1                
                                   
            pygame.draw.rect(self.screen, (0,0,0), (self.board.x, self.board.y, self.board.w*self.gridsize, self.board.h*self.gridsize), 1)
            
            if self.nextpiece is not None:
                for x,y in self.nextpiece.rotations[0]:
                    x1=(x+self.nextpiece.x+1)*self.gridsize
                    y1=(y+self.nextpiece.y+3)*self.gridsize
                
                    c1=self.nextpiece.color
                    c3=[max(0,v-100) for v in self.nextpiece.color]  #Outline Color                
                
                    pygame.draw.rect(self.screen, c1, (x1+1,y1+1,self.gridsize-2,self.gridsize-2),0)  #Base, filled
                    pygame.draw.rect(self.screen, c3, (x1,y1,self.gridsize,self.gridsize),1)          #Outline, pixel       
                    
                
            if self.lines>(3+self.level)**1.5:
                self.level+=1
                self.lvlsurf=self.level_font.render(str(self.level),1,(0,0,0),(255,255,255))
                
            pygame.display.update()        

def main():
    g=Game(7)
    g.run()
    
if __name__=="__main__":
    main()
